#include "editor/gui/roomeditor.hpp"

#include "editor/floodfillcommand.hpp"
#include "editor/pencommand.hpp"

#include <iostream>

namespace nmc
{
    RoomEditor::RoomEditor()
    {
        mTileMap = new TileMap();
        mRoomView = new RoomView(mTileMap);
        mRoomView->addActionListener(this);
        mRoomViewScrollArea = new gcn::ScrollArea(mRoomView);
        mRoomViewScrollArea->setScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS,
                                             gcn::ScrollArea::SHOW_ALWAYS);
        mRoomViewScrollArea->setBackgroundColor(gcn::Color(0x609090));
        mRoomViewScrollArea->setBorderSize(1);
        add(mRoomViewScrollArea);

        mRoomNavigation = new RoomNavigation();
        add(mRoomNavigation);

        mTileSelector = new TileSelector(); 
        add(mTileSelector);
        setBorderSize(1);

        mPen = new ImageRadioButton("icons/pen.bmp");
        mPen->setGroup("room-editor-tool");
        mPen->setMarked(true);
        mPen->addActionListener(this);
        add(mPen, 0, 0);
       
        mSelection = new ImageRadioButton("icons/selection.bmp");
        mSelection->setGroup("room-editor-tool");
        mSelection->addActionListener(this);
        add(mSelection, mPen->getWidth(), 0);
        
        mFloodFill = new ImageRadioButton("icons/floodfill.bmp");
        mFloodFill->setGroup("room-editor-tool");
        mFloodFill->addActionListener(this);
        add(mFloodFill, mPen->getWidth() * 2, 0);
                
        mFilledRectangle = new ImageRadioButton("icons/filledrectangle.bmp");
        mFilledRectangle->setGroup("room-editor-tool");
        mFilledRectangle->addActionListener(this);
        add(mFilledRectangle, mPen->getWidth() * 3, 0);
    }

    RoomEditor::~RoomEditor()
    {
        unsigned int i;
        for (i = 0; i < mCommandUndoHistory.size(); i++)
        {
            delete mCommandUndoHistory[i];
        }

        for (i = 0; i < mCommandRedoHistory.size(); i++)
        {
            delete mCommandRedoHistory[i];
        }

        delete mRoomView;
        delete mTileSelector;

        delete mPen;
        delete mSelection;
        delete mFloodFill;
        delete mFilledRectangle;
    }

    void RoomEditor::setRoomNumber(int roomNumber)
    {
        mTileMap->load(roomNumber);
    }

    void RoomEditor::setSize(int width, int height)
    {
        Container::setSize(width, height);
        
        mRoomViewScrollArea->setSize(width - getBorderSize() - 128 - 16 - 4 - 4, 
                                     height - getBorderSize() - 25 - 4);
        mRoomViewScrollArea->setPosition(4, 25);
        
        mTileSelector->setSize(128 + 12,
                               height - getBorderSize() - 25 - 100 - 4);
        mTileSelector->setPosition(500 - 4, 25);

        mRoomNavigation->setSize(128 + 12, 100 - 4);
        mRoomNavigation->setPosition(500 - 4, height - getBorderSize() - 100);
    }

    void RoomEditor::action(const gcn::ActionEvent& actionEvent)
    {
        if (actionEvent.getSource() == mPen)
        {
            mRoomView->setMode(RoomView::SELECT_TILES);  
        }
        else if (actionEvent.getSource() == mSelection)
        {
            mRoomView->setMode(RoomView::SELECT_AREA);  
        }
        else if (actionEvent.getSource() == mFloodFill)
        {
            mRoomView->setMode(RoomView::LOCKED);  
        }
        else if (actionEvent.getSource() == mFilledRectangle)
        {
            mRoomView->setMode(RoomView::SELECT_AREA);  
        }
        else if (actionEvent.getSource() == mRoomView)
        {
            if (mRoomView->getMode() == RoomView::SELECT_TILES
                && mPen->isMarked())
            {
                std::set<std::pair<int, int> > mSelectedTiles = mRoomView->getSelectedTiles();
                std::set<std::pair<int, int> >::iterator it;
                for (it = mSelectedTiles.begin(); it != mSelectedTiles.end(); it++)
                {
                    std::cout << it->first << " " << it->second << std::endl;
                    Command* command = new PenCommand(mTileMap,
                                                      it->first,
                                                      it->second,
                                                      mTileSelector->getSelectedTileNumber(),
                                                      mTileSelector->getSelectedTileFlags());
                    mCommandUndoHistory.push_back(command);
                    command->execute();   
                }                                           
            }
            else if (mRoomView->getMode() == RoomView::LOCKED
                     && mFloodFill->isMarked()
                     && mRoomView->isAreaSelected())
            {
                gcn::Rectangle rectangle = mRoomView->getSelectedArea();
                Command* command = new FloodFillCommand(mTileMap,
                                                        rectangle.x,
                                                        rectangle.y,
                                                        rectangle.width,
                                                        rectangle.height,
                                                        mTileSelector->getSelectedTileNumber(),
                                                        mTileSelector->getSelectedTileFlags());
                mCommandUndoHistory.push_back(command);
                command->execute();  
            }
            else if (mRoomView->getMode() == RoomView::SELECT_AREA
                     && mFilledRectangle->isMarked()
                     && mRoomView->isAreaSelected())
            {
                gcn::Rectangle rectangle = mRoomView->getSelectedArea();
                Command* command = new FloodFillCommand(mTileMap,
                                                        rectangle.x,
                                                        rectangle.y,
                                                        rectangle.width,
                                                        rectangle.height,
                                                        mTileSelector->getSelectedTileNumber(),
                                                        mTileSelector->getSelectedTileFlags());
                mCommandUndoHistory.push_back(command);
                command->execute();
                mRoomView->selectNone();
            }
        }
    }

    void RoomEditor::undo()
    {
        if (mCommandUndoHistory.empty())
        {
            return;
        }

        Command* command = mCommandUndoHistory.back();
        command->undo();
        mCommandRedoHistory.push_back(command);
        mCommandUndoHistory.pop_back();
    }

    void RoomEditor::redo()
    {
        if (mCommandRedoHistory.empty())
        {
            return;
        }

        Command* command = mCommandRedoHistory.back();
        command->execute();
        mCommandUndoHistory.push_back(command);
        mCommandRedoHistory.pop_back();
    }

    void RoomEditor::selectAll()
    {
        mRoomView->selectAll();
    }

    void RoomEditor::selectNone()
    {
        mRoomView->selectNone();
    }
}